package org.ainlolcat.ainscience.column.custom;

import org.ainlolcat.ainscience.Controller;
import org.ainlolcat.ainscience.UpdateListener;
import org.ainlolcat.ainscience.column.Column;
import org.ainlolcat.ainscience.column.CustomColumn;
import org.ainlolcat.ainscience.entity.Entity;
import org.ainlolcat.ainscience.matrix.MatrixFileParser;
import org.ainlolcat.ainscience.utils.executor.Executor;
import org.ainlolcat.ainscience.utils.executor.ExecutorProvider;
import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.Hashtable;

/**
 * @author ainlolcat
 *         Date: 5/4/13
 */
public class LinkedTableCustomColumn extends CustomColumn implements UpdateListener {
    private static Logger log = Logger.getLogger(LinkedTableCustomColumn.class);

    Hashtable<String, String> params;
    Entity entity;
    String linkedEntityName;
    String columnName;
    boolean registeredAsListener = false;

    @Override
    public Column generateColumn(Hashtable<String, String> params, Entity entity) {
        this.params = params;
        this.entity = entity;
        setType(MatrixFileParser.MATRIX_DELIMETER_TYPE_DOUBLE);
        linkedEntityName = params.get("entity");
        columnName = params.get("column");
        generateValues();
        return this;
    }

    private void generateValues(){
        Executor executor = ExecutorProvider.getExecutor(entity);
        try {
            Double multiplication = params.get("mult") != null ? Double.parseDouble(executor.execute(params.get("mult")).getStringValue()) : 1 ;
            int rate = params.get("rate") != null ? (int) Double.parseDouble(executor.execute(params.get("rate")).getStringValue()) : 1 ;
            log.debug("Rate: " + rate + ". Multiplication coefficient: " + multiplication);

            Entity linkedEntity = Controller.getInstance().getProject().getEntityByName(linkedEntityName);
            Column linkedColumn = linkedEntity.getColumnByName(columnName) ;

            if (!registeredAsListener) Controller.getInstance().addUpdateListener(this);
            registeredAsListener = true;

            if (linkedColumn == null || linkedColumn.size() == 0) {
                log.debug("Wait for better time because " + columnName + " size " + (linkedColumn!=null?linkedColumn.size():0));
                return;
            }

            values = new ArrayList();
            double[] data = linkedColumn.getDoubleRepresentation();

            for (int i=0;i<entity.getRowCount();i++){
                double temp = 0;
                for (int j = 0 ; j < rate ; j++){
                    int idx = i * rate + j;
                    temp += idx < data.length ? data[idx] : 0;
                }
                temp = temp * multiplication;
                values.add(temp);
            }
            Controller.getInstance().throwUpdateEvent(entity, UPDATE_ENTITY_COLUMN);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void onProjectUpdate() {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    public void onEntityUpdate(Entity entity, int action) {
        log.debug("Update event income for entity " + entity.getName() + " while linked one " + linkedEntityName + "[" + columnName + "] to " + entity.getName());
        if (entity.getName().equals(linkedEntityName))
            generateValues();
    }
}
